#include "wxsqlite3.h"
#include <wx/tokenzr.h>
#include <wx/filename.h>

wxSQLite3Database::wxSQLite3Database(void)
{
#ifdef __WXMSW__
	db_command = _T("sqlite3.exe");
#else
	db_command = _T("/usr/bin/sqlite3");
#endif
	db_option = _T(",");
	commited = false;
	is_opened = false;
	is_updated = false;
}
wxSQLite3Database::~wxSQLite3Database(void)
{
	Close();
}
void wxSQLite3Database::Open(const wxString &filename, bool autocommit)
{
	db_filepath = filename;
	is_autocommit = autocommit;
	if (!is_autocommit) {
		create_TempDB();
	}
	is_opened = true;
}
void wxSQLite3Database::SetOption(const wxString &option)
{
	db_option = option;
}
void wxSQLite3Database::Close(void)
{
	if (IsOpened()) {
		Commit();
		delete_TempDB();
		db_filepath.Clear();
		tmp_filepath.Clear();
		commited = false;
		is_opened = false;
		is_updated = false;
	}
}
void wxSQLite3Database::Commit(void)
{
	if (!IsOpened()) return;
	if (!is_autocommit && !commited) {
		commit_TempDB();
		commited = true;
		is_updated = false;
	}
}
void wxSQLite3Database::Rollback(void)
{
	if (!IsOpened()) return;
	if (!is_autocommit) {
		rollback_TempDB();
		commited = false;
		is_updated = false;
	}
}
int wxSQLite3Database::ExecuteUpdate(const wxString &sql)
{
	if (!IsOpened()) return -1; 
	wxArrayString output, errors;
	int ret = wxExecute(wxString::Format(_T("%s -separator %s %s \"%s\" "),db_command,db_option,GetCurrentPath(),sql),output,errors);
	if (!is_autocommit) {
		commited = false;
	}
	is_updated = true;
	return ret;
}
int wxSQLite3Database::ExecuteUpdate(wxSQLite3Statement &sql)
{
	return ExecuteUpdate(sql.GetSQL());
}
wxSQLite3ResultSet wxSQLite3Database::ExecuteQuery(const wxString &sql)
{
	wxSQLite3ResultSet nulset;
	if (!IsOpened()) return nulset;
	wxArrayString output, errors;
	int ret = wxExecute(wxString::Format(_T("%s -separator %s %s \"%s\" "),db_command,db_option,GetCurrentPath(),sql),output,errors);
	wxSQLite3ResultSet rset(output,db_option);
	//wxMessageBox(wxString::Format(_T("output: %d"),output.GetCount()),_T("abc"),wxOK,NULL);
	if (!is_autocommit) {
		commited = false;
	}
	return rset;
}
wxSQLite3ResultSet wxSQLite3Database::ExecuteQuery(wxSQLite3Statement &sql)
{
	return ExecuteQuery(sql.GetSQL());
}
void wxSQLite3Database::create_TempDB(void)
{
	wxFileName fname(db_filepath);
	tmp_filepath = wxFileName::CreateTempFileName(fname.GetName());
	if (fname.FileExists()) {
		wxCopyFile(fname.GetFullPath(),tmp_filepath);
	}
}
void wxSQLite3Database::commit_TempDB(void)
{
	wxFileName fname(db_filepath);
	if (fname.FileExists()) {
		wxRemoveFile(fname.GetFullPath());
	}
	wxCopyFile(tmp_filepath,fname.GetFullPath());
}
void wxSQLite3Database::rollback_TempDB(void)
{
	delete_TempDB();
	create_TempDB();
}
void wxSQLite3Database::delete_TempDB(void)
{
	wxFileName fname(tmp_filepath);
	if (fname.FileExists()) {
		wxRemoveFile(fname.GetFullPath());
	}
}



//---wxSQLite3ResultSet
wxSQLite3ResultSet::wxSQLite3ResultSet(wxArrayString &content, wxString &option)
{
	db_content = content;
	db_option = option;
	index = -1;
}
int wxSQLite3ResultSet::GetInt(int column)
{
	int cnt = 0;
	wxStringTokenizer toks(db_content[index],db_option);
	while (toks.HasMoreTokens()) {
		wxString result = toks.GetNextToken();
		if (column == cnt) {
			long tmp;
			if (result.ToLong(&tmp)) {
				return (int)tmp;
			}else{
				return -1;
			}
		}
		cnt++;
	}
	return 0;
}
wxString wxSQLite3ResultSet::GetString(int column)
{
	int cnt = 0;
	wxStringTokenizer toks(db_content[index],db_option);
	while (toks.HasMoreTokens()) {
		wxString result = toks.GetNextToken();
		if (column == cnt) {
			return result;
		}
		cnt++;
	}
	return _T("");
}
bool wxSQLite3ResultSet::GetBool(int column)
{
	int cnt = 0;
	wxStringTokenizer toks(db_content[index],db_option);
	while (toks.HasMoreTokens()) {
		wxString result = toks.GetNextToken();
		if (column == cnt) {
			return (result == _T("0") ? false : true);
		}
		cnt++;
	}
	return false;
}
wxDateTime wxSQLite3ResultSet::GetDate(int column)
{
	int cnt = 0;
	wxStringTokenizer toks(db_content[index],db_option);
	while (toks.HasMoreTokens()) {
		wxString result = toks.GetNextToken();
		if (column == cnt) {
			wxDateTime dt;
			if (dt.ParseDate(result) != NULL) {
				return dt;
			}else{
				return wxInvalidDateTime;
			}
		}
		cnt++;
	}
	return wxDateTime::Now();
}
bool wxSQLite3ResultSet::NextRow(void)
{
	index++;
	if (index >= db_content.GetCount()) {
		return false;
	}
	return true;
}